#include "ContrastEnhancementAlgorithm.h"
#include <QImage>
#include <QDebug>
#include <QRgb>
#include <vector>
#include <algorithm>
#include <cmath>
#include <QElapsedTimer>
#include <QDateTime>

ContrastEnhancementAlgorithm::ContrastEnhancementAlgorithm(QObject *parent)
    : ImageProcessingAlgorithmBase(parent),
      m_settingsForm(nullptr),
      m_enhancementStrength(50), // 默认增强强度为50%
      m_processed(false), // 初始为未处理状态
      m_autoEnhancementEnabled(false), // 初始关闭自动增强
      m_lastProcessTime(0) // 初始化上次处理时间
{
    // 构造函数初始化成员变量
}

ContrastEnhancementAlgorithm::~ContrastEnhancementAlgorithm()
{
    // 释放设置表单资源
    if (m_settingsForm)
    {
        m_settingsForm = nullptr;
    }
}

void ContrastEnhancementAlgorithm::initialize()
{
    // 创建设置表单
    m_settingsForm = new ContrastEnhancementSettingsForm();
    m_settingsForm->setObjectName(algorithmName());

    // 初始化设置表单的增强强度
    m_settingsForm->setEnhancementStrength(m_enhancementStrength);

    // 连接设置变更信号
    connect(m_settingsForm, SIGNAL(enhancementStrengthChanged(int)),
            this, SLOT(onSettingsChanged(int)));
    
    // 连接自动增强按钮点击信号
    connect(m_settingsForm, SIGNAL(autoEnhanceClicked()),
            this, SLOT(autoEnhanceContrast()));

    // 发出注册widget信号
    emit registerAlgorithmWidget(algorithmName(), m_settingsForm, ":/images/images/contrastRatio.png");
}

QString ContrastEnhancementAlgorithm::algorithmName() const
{
    return QString("对比度增强");
}

void ContrastEnhancementAlgorithm::setEnhancementStrength(int strength)
{
    // 确保强度在有效范围内
    m_enhancementStrength = qBound(0, strength, 100);

    // 更新设置表单
    if (m_settingsForm)
    {
        m_settingsForm->setEnhancementStrength(m_enhancementStrength);
    }
}

int ContrastEnhancementAlgorithm::enhancementStrength() const
{
    return m_enhancementStrength;
}

void ContrastEnhancementAlgorithm::onSettingsChanged(int strength)
{
    // 更新增强强度
    setEnhancementStrength(strength);

    // 可以在这里添加日志或其他处理
    qDebug() << "Contrast enhancement strength changed to:" << strength;

    // 如果已经设置了输入图像，进行处理
    if (!m_inputImage.isNull()) {
        // 获取当前时间
        qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
        
        // 设置时间间隔阈值（毫秒），避免处理过于频繁
        const int processInterval = 200;
        
        // 检查是否超过时间间隔
        if (currentTime - m_lastProcessTime >= processInterval) {
            processImage("");
            m_lastProcessTime = currentTime;
        }
    }
}

void ContrastEnhancementAlgorithm::setInputImage(const QString &imageId, const QImage &inputImage)
{
    // 更换图像时重置为默认参数
    resetToDefaultParameters();
    m_imageId = imageId;
    m_inputImage = inputImage;

    
    // 对新图像进行自动对比度增强
    // 只有在首次加载图像且未手动设置过增强强度时才自动增强
    if (!m_processed && !m_autoEnhancementEnabled) {
        m_autoEnhancementEnabled = true;
        // Directly call autoEnhanceContrast instead of using QTimer::singleShot
        autoEnhanceContrast();
    }
}

QString ContrastEnhancementAlgorithm::currentImageId() const
{
    return m_imageId;
}

void ContrastEnhancementAlgorithm::processImage(const QString& parameters)
{
    Q_UNUSED(parameters)
    if (m_inputImage.isNull()) {
        qWarning() << "No input image set for contrast enhancement processing";
        emit imageProcessed(m_imageId, QImage());
        return;
    }

    QImage outputImage = m_inputImage.convertToFormat(QImage::Format_Grayscale8);
    int width = outputImage.width();
    int height = outputImage.height();
    int totalPixels = width * height;

    // 计算灰度直方图
    std::vector<int> histogram(256, 0);
    for (int y = 0; y < height; ++y) {
        const uchar *line = outputImage.scanLine(y);
        for (int x = 0; x < width; ++x) {
            uchar gray = line[x];
            histogram[gray]++;
        }
    }

    // 计算累积分布函数
    std::vector<int> cdf(256, 0);
    cdf[0] = histogram[0];
    for (int i = 1; i < 256; ++i) {
        cdf[i] = cdf[i-1] + histogram[i];
    }

    // 直方图均衡化映射基础上应用增强强度
    uchar minCdf = *std::min_element(cdf.begin(), cdf.end());
    double enhancementFactor = 1.0 + (m_enhancementStrength / 100.0) * 2.0; // 1.0-3.0

    for (int y = 0; y < height; ++y) {
        uchar *line = outputImage.scanLine(y);
        for (int x = 0; x < width; ++x) {
            uchar gray = line[x];
            double normalized = (cdf[gray] - minCdf) / (double)(totalPixels - minCdf);

            // 应用增强因子 - 非线性增强
            double enhanced = std::pow(normalized, 1.0 / enhancementFactor);
            uchar newGray = static_cast<uchar>(enhanced * 255.0);

            line[x] = newGray;
        }
    }

    // 处理完成后标记为已处理
    m_processed = true;
    
    // 发送处理完成结果
    emit imageProcessed(m_imageId, outputImage.convertToFormat(m_inputImage.format()));
}

QVariantMap ContrastEnhancementAlgorithm::getProcessParameters() const
{
    QVariantMap params;
    params["algorithmName"] = algorithmName();
    params["enhancementStrength"] = m_enhancementStrength;
    params["imageId"] = m_imageId;
    params["processed"] = m_processed;
    return params;
}

void ContrastEnhancementAlgorithm::setProcessParameters(const QVariantMap &params)
{
    // 检查并设置增强强度参数
    if (params.contains("enhancementStrength")) {
        int strength = params["enhancementStrength"].toInt();
        setEnhancementStrength(strength);
    }
    
    // 检查并设置处理状态参数（如果需要）
    if (params.contains("processed")) {
        m_processed = params["processed"].toBool();
    }
}

void ContrastEnhancementAlgorithm::resetToDefaultParameters()
{
    // 恢复默认增强强度
    m_enhancementStrength = 50; // 默认增强强度为50%
    
    // 重置处理状态
    m_processed = false;
    
    // 重置自动增强标志
    m_autoEnhancementEnabled = false;
    
    // 清除设置的图像数据
    m_inputImage = QImage();
    m_imageId.clear();
    
    // 更新设置表单，但避免触发信号循环
    if (m_settingsForm) {
        // 断开信号连接，避免触发enhancementStrengthChanged信号
        disconnect(m_settingsForm, SIGNAL(enhancementStrengthChanged(int)),
                   this, SLOT(onSettingsChanged(int)));
        
        // 更新设置表单
        m_settingsForm->setEnhancementStrength(m_enhancementStrength);
        
        // 重新连接信号
        connect(m_settingsForm, SIGNAL(enhancementStrengthChanged(int)),
                this, SLOT(onSettingsChanged(int)));
    }
    
    qDebug() << "Contrast enhancement parameters reset to default values and cleared image data";
}

void ContrastEnhancementAlgorithm::autoEnhanceContrast()
{
    if (m_inputImage.isNull()) {
        qWarning() << "Cannot perform auto contrast enhancement on null image";
        return;
    }
    
    int width = m_inputImage.width();
    int height = m_inputImage.height();
    int pixelCount = width * height;
    
    // 计算灰度直方图和色彩通道统计
    std::vector<int> grayHistogram(256, 0);
    std::vector<int> rHistogram(256, 0);
    std::vector<int> gHistogram(256, 0);
    std::vector<int> bHistogram(256, 0);
    
    double meanBrightness = 0.0;
    double variance = 0.0;
    int colorfulnessCount = 0;
    
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            QRgb pixel = m_inputImage.pixel(x, y);
            int r = qRed(pixel);
            int g = qGreen(pixel);
            int b = qBlue(pixel);
            
            // 计算灰度值
            int gray = qGray(pixel);
            grayHistogram[gray]++;
            
            // 色彩通道直方图
            rHistogram[r]++;
            gHistogram[g]++;
            bHistogram[b]++;
            
            // 累计亮度用于计算平均值
            meanBrightness += gray;
            
            // 检测彩色像素（通道差异大于阈值）
            int maxChannel = std::max({r, g, b});
            int minChannel = std::min({r, g, b});
            if (maxChannel - minChannel > 15) {
                colorfulnessCount++;
            }
        }
    }
    
    // 计算平均亮度
    meanBrightness /= pixelCount;
    
    // 计算亮度方差（对比度的一种度量）
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            int gray = qGray(m_inputImage.pixel(x, y));
            variance += std::pow(gray - meanBrightness, 2);
        }
    }
    variance /= pixelCount;
    double stdDev = std::sqrt(variance); // 标准差
    
    // 计算实际的最小和最大灰度值（自适应百分位）
    // 根据图像特性调整百分位值
    double percentile = (stdDev < 30) ? 0.5 : 1.0; // 低对比度图像使用更低的百分位
    int lowerThreshold = static_cast<int>(pixelCount * percentile / 100);
    int upperThreshold = static_cast<int>(pixelCount * (100 - percentile) / 100);
    
    int minGray = 0, maxGray = 255;
    int cumulativeCount = 0;
    
    // 找到实际的最小灰度值
    for (int i = 0; i < 256; ++i) {
        cumulativeCount += grayHistogram[i];
        if (cumulativeCount >= lowerThreshold) {
            minGray = i;
            break;
        }
    }
    
    cumulativeCount = 0;
    // 找到实际的最大灰度值
    for (int i = 255; i >= 0; --i) {
        cumulativeCount += grayHistogram[i];
        if (cumulativeCount >= lowerThreshold) {
            maxGray = i;
            break;
        }
    }
    
    // 计算灰度范围
    int dynamicRange = maxGray - minGray;
    
    // 计算直方图分布的偏度，判断图像是偏暗还是偏亮
    double skewness = 0.0;
    for (int i = 0; i < 256; ++i) {
        if (grayHistogram[i] > 0) {
            double normalizedGray = (i - meanBrightness) / stdDev;
            skewness += grayHistogram[i] * std::pow(normalizedGray, 3);
        }
    }
    skewness /= pixelCount;
    
    // 基于多种因素计算适当的增强强度
    int autoStrength = 50; // 默认值
    
    // 主要基于动态范围和标准差确定基础增强强度
    if (dynamicRange < 40 || stdDev < 20) {
        // 极低对比度图像，需要最强增强
        autoStrength = 95;
    } else if (dynamicRange < 70 || stdDev < 35) {
        // 低对比度图像，需要强增强
        autoStrength = 85;
    } else if (dynamicRange < 100 || stdDev < 50) {
        // 中等对比度图像，适度增强
        autoStrength = 70;
    } else if (dynamicRange < 150 || stdDev < 65) {
        // 较好对比度图像，轻度增强
        autoStrength = 50;
    } else {
        // 高对比度图像，轻微增强
        autoStrength = 30;
    }
    
    // 根据亮度分布调整增强强度
    // 对于过暗或过亮的图像需要特殊处理
    if (meanBrightness < 60 && skewness > 0) { // 过暗图像
        autoStrength += 10;
    } else if (meanBrightness > 190 && skewness < 0) { // 过亮图像
        autoStrength += 10;
    }
    
    // 对于彩色图像，可以略微降低增强强度，避免颜色失真
    double colorRatio = static_cast<double>(colorfulnessCount) / pixelCount;
    if (colorRatio > 0.3) { // 明显彩色图像
        autoStrength = std::max(20, autoStrength - 10);
    }
    
    // 确保增强强度在有效范围内
    autoStrength = qBound(0, autoStrength, 100);
    
    qDebug() << "Auto contrast enhancement: dynamic range=" << dynamicRange 
             << " stdDev=" << stdDev << " meanBrightness=" << meanBrightness 
             << " skewness=" << skewness << " colorRatio=" << colorRatio 
             << " autoStrength=" << autoStrength;
    
    // 设置自动计算的增强强度
    setEnhancementStrength(autoStrength);
    
    // 执行图像处理
    processImage("");
}
